package com.zxx.pattern.adapterPattern;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;

import com.zxx.designpattern.R;

/**
 * 圆形菜单
 * @author zxx on 2021/7/12
 */
public class CircleMenuLayout extends ViewGroup {

    private static final float RADIO_DEFAULT_CHILD_DIMENSION = 1 / 4f;  //该容器内child item的默认尺寸
    private static final float RADIO_PADDING_LAYOUT = 1 / 12f;          //该容器的内边距，无视padding属性，如需边距请用该变量
    private int mRadius;        //圆形直径

    private float mPadding;     //该容器的内边距，无视padding属性，如需边距请用该变量
    private double mStartAngle = 0;     //布局时开始角度
    private String[] mItemTexts;        //菜单项文本
    private int[] mItemImgs;            //菜单项图标
    private int mMenuItemCount;         //菜单个数
    private int mMenuItemLayoutId = R.layout.circle_menu_item;  //菜单布局资源id

    private OnItemClickListener mOnItemClickListener;           //item点击事件接口

    public CircleMenuLayout(Context context) {
        this(context, null);
    }

    public CircleMenuLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //无视padding
        setPadding(0, 0, 0, 0);
    }

    public CircleMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    //设置菜单项条目的图标与文本
    public void setMenuItemIconsAndTexts(int[] images, String[] texts) {
        if (images == null && texts == null) {
            throw new IllegalArgumentException("菜单项文本和图片至少设置其一");
        }
        mItemImgs = images;
        mItemTexts = texts;

        //初始化数量
        mMenuItemCount = images == null ? texts.length : images.length;
        if (images != null && texts != null) {
            mMenuItemCount = Math.min(images.length, texts.length);
        }

        //构建菜单项
        //buildMenuItems();
        buildMenuItems2();
    }

    //-----
    //构建菜单项
    private void buildMenuItems() {
        //根据用户设置的参数，初始化item
        for (int i = 0; i < mMenuItemCount; i++) {
            View itemView = inflateMenuView(i);

            initMenuItem(itemView, i);  //初始化菜单项

            addView(itemView);          //添加view到容器内
        }
    }

    private void initMenuItem(View itemView, int childIndex) {
        ImageView iv = itemView.findViewById(R.id.circle_menu_image);
        TextView tv = itemView.findViewById(R.id.circle_menu_text);
        iv.setVisibility(VISIBLE);
        iv.setImageResource(mItemImgs[childIndex]);
        tv.setVisibility(VISIBLE);
        tv.setText(mItemTexts[childIndex]);
    }

    private View inflateMenuView(final int childIndex) {
        LayoutInflater mInflater = LayoutInflater.from(getContext());
        View itemView = mInflater.inflate(mMenuItemLayoutId, this, false);
        itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnItemClickListener != null) {
                    mOnItemClickListener.onClick(v, childIndex);
                }
            }
        });
        return itemView;
    }
    //--------

    //设置布局的宽高，并测量item的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //测量自身尺寸
        measureMyself(widthMeasureSpec, heightMeasureSpec);
        //测量菜单项尺寸
        measureChildViews();
    }

    private void measureMyself(int widthMeasureSpec, int heightMeasureSpec) {
        int resWidth = 0;
        int resHeight = 0;
        //根据传入的参数，分别获取测量模式和测量值
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        //如果宽或高的测量模式非精确模式
        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            //主要设置为背景图的高度
            resWidth = getSuggestedMinimumWidth();
            //如果未设置背景图片，则设置为屏幕宽高的默认值
            resWidth = resWidth == 0 ? getDefaultWidth() : resWidth;

            resHeight = getSuggestedMinimumHeight();
            resHeight = resHeight == 0 ? getDefaultWidth() : resHeight;
        } else {
            resWidth = resHeight = Math.min(width, height);
        }

        setMeasuredDimension(resWidth, resHeight);
    }

    //屏幕宽高的默认值(未写)
    private int getDefaultWidth() {
        return 0;
    }

    private void measureChildViews() {
        //获得半径
        mRadius = Math.max(getMeasuredWidth(), getMeasuredHeight());
        //item数量
        int count = getChildCount();
        //item尺寸
        int childSize = (int) (mRadius * RADIO_DEFAULT_CHILD_DIMENSION);
        //item测量模式
        int childMode = MeasureSpec.EXACTLY;

        //迭代测量
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            //计算item的尺寸，以及设置模式，去对item进行测量
            int makeMeasureSpec = -1;
            makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, childMode);
            child.measure(makeMeasureSpec, makeMeasureSpec);
        }

        mPadding = RADIO_PADDING_LAYOUT * mRadius;
    }

    //布局item的位置
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int childCount = getChildCount();
        int left, top;
        //item的尺寸
        int itemWidth = (int) (mRadius * RADIO_DEFAULT_CHILD_DIMENSION);

        //根据item的个数，计算item的布局占用的角度
        float angleDelay = 360 / childCount;

        //遍历所有菜单项，设置他们的位置
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            //菜单项的起始角度
            mStartAngle %= 360;
            //计算中心点到item中心的距离
            float distanceFromCenter = mRadius / 2f - itemWidth / 2 - mPadding;
            //distanceFromCenter cosa即item中心点的left坐标
            left = mRadius / 2 + (int) Math.round(distanceFromCenter
                    * Math.cos(Math.toRadians(mStartAngle)) - 1 / 2f
                    * itemWidth);

            //distanceFromCenter sina即item中心点的纵坐标
            top = mRadius / 2 + (int) Math.round(distanceFromCenter
                    * Math.sin(Math.toRadians(mStartAngle)) - 1 / 2f
                    * itemWidth);

            //布局child view
            child.layout(left, top, left + itemWidth, top + itemWidth);

            //叠加尺寸
            mStartAngle += angleDelay;
        }
    }

    public interface OnItemClickListener {
        void onClick(View view, int index);
    }

    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }


    //--------------利用Adapter 自定义圆形菜单--------------
    private ListAdapter mAdapter;

    public void setAdapter(ListAdapter mAdapter) {
        this.mAdapter = mAdapter;
    }

    //根据用户设置的参数，初始化item
    private void buildMenuItems2() {
        for (int i = 0; i < mAdapter.getCount(); i++) {
            final View itemView = mAdapter.getView(i, null, this);
            final int position = i;
            itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickListener != null) {
                        mOnItemClickListener.onClick(itemView, position);
                    }
                }
            });
            addView(itemView);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        if (mAdapter != null) {
            buildMenuItems2();
        }
        super.onAttachedToWindow();
    }

    static class MenuItem{
        public int imageId;
        public String title;

        public MenuItem(int imageId, String title) {
            this.imageId = imageId;
            this.title = title;
        }
    }

}
